package mychi

import (
	"context"
	"net/http"
	"strings"
)

var (
	RouteCtxKey = &contextKey{"RouteContext"}
)

type Context struct {
	Routes           Routes
	parentCtx        context.Context
	RoutePath        string
	RouteMethod      string
	URLParams        RouteParams
	routeParams      RouteParams
	routePattern     string
	RoutePatterns    []string
	methodsAllowed   []methodTyp
	methodNotAllowed bool
}

type RouteParams struct {
	Keys, Values []string
}

type contextKey struct {
	name string
}

func URLParam(r *http.Request, key string) string {
	if rctx := RouteContext(r.Context()); rctx != nil {
		return rctx.URLParam(key)
	}
	return ""
}

func URLParamFromCtx(ctx context.Context, key string) string {
	if rctx := RouteContext(ctx); rctx != nil {
		return rctx.URLParam(key)
	}
	return ""
}

func RouteContext(ctx context.Context) *Context {
	val, _ := ctx.Value(RouteCtxKey).(*Context)
	return val
}

func NewRouteContext() *Context {
	return &Context{}
}

func replaceWildcards(p string) string {
	for strings.Contains(p, "/*/") {
		p = strings.ReplaceAll(p, "/*/", "/")
	}
	return p
}

func (x *Context) URLParam(key string) string {
	for k := len(x.URLParams.Keys) - 1; k >= 0; k-- {
		if x.URLParams.Keys[k] == key {
			return x.URLParams.Values[k]
		}
	}
	return ""
}

func (x *Context) Reset() {
	x.Routes = nil
	x.RoutePath = ""
	x.RouteMethod = ""
	x.RoutePatterns = x.RoutePatterns[:0]
	x.URLParams.Keys = x.URLParams.Keys[:0]
	x.URLParams.Values = x.URLParams.Values[:0]

	x.routePattern = ""
	x.routeParams.Keys = x.routeParams.Keys[:0]
	x.routeParams.Values = x.routeParams.Values[:0]
	x.methodNotAllowed = false
	x.methodsAllowed = x.methodsAllowed[:0]
	x.parentCtx = nil
}

func (x *Context) RoutePattern() string {
	if x == nil {
		return ""
	}
	routePattern := strings.Join(x.RoutePatterns, "")
	routePattern = replaceWildcards(routePattern)
	if routePattern != "/" {
		routePattern = strings.TrimSuffix(routePattern, "//")
		routePattern = strings.TrimSuffix(routePattern, "/")
	}
	return routePattern
}

func (s *RouteParams) Add(key, value string) {
	s.Keys = append(s.Keys, key)
	s.Values = append(s.Values, value)
}

func (k *contextKey) String() string {
	return "chi context value " + k.name
}
